package com.lipaluma.field.validator.impl.date;

import java.lang.reflect.Field;
import java.util.Date;

import org.apache.commons.lang.StringUtils;

import com.lipaluma.Xml;
import com.lipaluma.annotations.validations.ValidateDate;
import com.lipaluma.context.Context;
import com.lipaluma.exceptions.CsvParserException;
import com.lipaluma.field.validator.impl.generic.AbstractConstantValidator;
import com.lipaluma.util.ParserUtils;
import com.lipaluma.xml.validator.XmlConstantValidator;
import com.lipaluma.xml.validator.XmlValidator;

/**
 * Validate a {@link Date} type field to check if all value for the field is constant.<br/>
 * A value can be supplied or not. 
 * <ul>
 * <li>If the value is supplied, all values of the source must be equal to that value</li>
 * <li>If not, the first value encountered will be the constant to respect for all others.</li>
 * </ul>
 * The pattern is mandatory if the supplied value is given.
 * 
 * <p>
 * For Initialisation :
 * <ul>
 * 	<li>
 * 	<u><b>By annotations :</b></u> Use {@link ValidateDate}, with the attribute <code>constant = true</code>. <br/>
 * To supply a value, put <code>constantSupplied = true</code> and the value supplied in <code>constantValue</code> attribute.<br/>
 * The attribute <code>pattern</code> must be initialized to indicate the format of the supplied value.
 * </li>
 * 	<li>
 * 	<u><b>By Xml :</b></u>
 * <ul>
 * <li>
 * See the example below to add a constant validator without supplied value : <br/>
 * <code>
 * &lt;ToMap field="..."   ...><br/>
 * &nbsp;&nbsp;&nbsp;<b>&lt;constant/></b><br/>
 * &lt;/ToMap>
 * </code>
 * <br/>
 * </li>
 * <li>
 * See this other example to add a constant validator with a supplied value : <br/>
 * <code>
 * &lt;ToMap field="..."   ...><br/>
 * &nbsp;&nbsp;&nbsp;<b>&lt;constant pattern="yyyy-MM-dd">2013-10-03&lt;/constant></b><br/>
 * &lt;/ToMap>
 * </code>
 * <br/>
 * A pattern is mandatory to indicate the format of the supplied value.
 * </li>
 * </li>
 * </ul>
 * @author Mario
 *
 */
public class DateConstantValidator extends AbstractConstantValidator<Date> {
	public DateConstantValidator() {}
	public DateConstantValidator(Date constant) {
		super(constant);
	}
	
	@Override
	public boolean init(Context context, Field field) {
		ValidateDate annotation = field.getAnnotation(ValidateDate.class);
		if(annotation == null || !annotation.constant())
			return false;
		
		if(StringUtils.isEmpty(annotation.pattern()) && annotation.constantSupplied())
			throw new CsvParserException("Error on field "+field.getName()+" : The ValidateDate annotation must have a non empty pattern when a constant value is supplied");
		if(annotation.constantSupplied()) {
			init((Date)ParserUtils.parseToType(field.getType(), annotation.constantValue(), annotation.pattern()));
		}
		return true;
	}

	@Override
	public boolean init(Context context, Field field, XmlValidator xmlValidator) {
		XmlConstantValidator validator = (XmlConstantValidator) xmlValidator;
		String pattern = validator.getPattern();
		if(StringUtils.isEmpty(pattern) && validator.getConstantValue() != null)
			throw new CsvParserException("Error on field "+field.getName()+" : The "+XmlConstantValidator.CONSTANT+" validator element for Date must have a valid '"+Xml.PATTERN+"' attribute when the value is supplied");

		if(validator.getConstantValue() != null)
			init((Date)ParserUtils.parseToType(field.getType(), validator.getConstantValue(), pattern));
		return true;
	}	

}
